from sqlalchemy import Column, String, VARCHAR, TIMESTAMP, ForeignKey, Integer
from sqlalchemy.dialects.mysql import BIGINT, INTEGER, TINYINT, SMALLINT
from sqlalchemy.ext.declarative import declarative_base  # ORM(对象关系映射)的基类
from datetime import datetime
from app.config import DEFAULT_AVATAR

Base = declarative_base()


class ExtendedBase(Base):
    __abstract__=True
    create_at = Column(TIMESTAMP, default=None, server_default='CURRENT_TIMESTAMP',nullable=False, comment="创建时间")
    update_at = Column(TIMESTAMP, default=None, server_default='CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', nullable=False, comment="更新时间")
    def to_dict(self):
        obj_dict = {}
        for column in self.__table__.columns.keys():
            val = getattr(self, column)
            if isinstance(val, datetime):
                val = str(val)
            obj_dict[column] = val
        return obj_dict


# User类 用户类 继承ExtendedBase基类
class User(ExtendedBase):
    __tablename__ = "user"
    id = Column(BIGINT(unsigned = True), primary_key=True, autoincrement=True, comment="用户ID")
    username = Column(String(11), default=None, nullable=False, unique=True, comment="用户账号")
    password = Column(String(20), default=None, nullable=False, comment="用户账号密码")
    nickname = Column(String(32), default=None, nullable=False, unique=True, comment="用户昵称")
    avatar = Column(VARCHAR(255), default=DEFAULT_AVATAR, nullable=False, comment="用户头像路径")
    
    # 重写to_dict方法，防止敏感信息泄露
    def to_dict(self):
        obj_dict = {}
        for column in self.__table__.columns.keys():
            if column == "password":
                continue
            val = getattr(self, column)
            if isinstance(val, datetime):
                val = str(val)
            obj_dict[column] = val
        return obj_dict
    
# Group类 用户组类 继承ExtendedBase基类
class Group(ExtendedBase):
    __tablename__ = "group"
    id = Column(BIGINT(unsigned = True), primary_key=True, autoincrement=True, comment="映射用户组ID")
    group_id = Column(BIGINT(unsigned = True),  ForeignKey("group_detail.id"), nullable=False, comment="用户组ID")
    user_id = Column(BIGINT(unsigned = True), ForeignKey("user.id") ,nullable=False, comment="群组内用户ID")
    permission = Column(TINYINT, default=None, nullable=False, unique=True, comment="用户权限")
    
# GroupDetail类 用户组类 继承ExtendedBase基类
class GroupDetail(ExtendedBase):
    __tablename__ = "group_detail"
    id = Column(BIGINT(unsigned = True), primary_key=True, autoincrement=True, comment="用户组ID")
    user_id = Column(BIGINT(unsigned = True), ForeignKey("user.id") ,nullable=False, comment="群组，创建者ID")
    group_name = Column(VARCHAR(255), default=None, nullable=False, comment="用户组名")

# Hub类 知识库类 继承ExtendedBase基类
class Hub(ExtendedBase):
    __tablename__ = "hub"
    id = Column(BIGINT(unsigned = True), primary_key=True, autoincrement=True, comment="知识库ID")
    group_id = Column(BIGINT(unsigned = True), ForeignKey("group_detail.id") ,nullable=False, comment="用户组ID") 
    user_id = Column(BIGINT(unsigned = True), ForeignKey("user.id") ,nullable=False, comment="创建者ID")
    chunk_size = Column(INTEGER, default=500, nullable=False, unique=False, comment="文件处理状态")
    overlap = Column(INTEGER, default=100, nullable=False, unique=False, comment="文件处理状态")
    hub_name = Column(VARCHAR(255), default=None, nullable=False, comment="知识库名")
    description = Column(VARCHAR(1023), default=None, nullable=False, comment="知识库描述")

# File类 上传文件类 继承ExtendedBase基类
class File(ExtendedBase):
    __tablename__ = "file"
    id = Column(BIGINT(unsigned = True), primary_key=True, autoincrement=True, comment="用户组ID")
    user_id = Column(BIGINT(unsigned = True), ForeignKey("user.id") ,nullable=False, comment="用户ID")
    hub_id = Column(BIGINT(unsigned = True), ForeignKey("hub.id") ,nullable=False, comment="知识库ID")
    file_name = Column(VARCHAR(255), default=None, nullable=False, comment="文件名")
    state = Column(TINYINT, default=0, nullable=False, unique=False, comment="文件处理状态")

class Database(ExtendedBase):
    __tablename__ = "database"
    id = Column(BIGINT(unsigned = True), primary_key=True, autoincrement=True, comment="用户组ID")
    user_id = Column(BIGINT(unsigned = True), ForeignKey("user.id") ,nullable=False, comment="用户ID")
    hub_id = Column(BIGINT(unsigned = True), ForeignKey("hub.id") ,nullable=False, comment="知识库ID")
    ip = Column(VARCHAR(16), default=None, nullable=False, comment="数据库IP地址")
    port = Column(SMALLINT, default=None, nullable=False, comment="数据库端口号")
    database = Column(VARCHAR(255), default=None, nullable=False, comment="数据库名")
    username = Column(VARCHAR(255), default=None, nullable=False, comment="数据库用户名")
    password = Column(VARCHAR(255), default=None, nullable=False, comment="数据库密码")
    type = Column(VARCHAR(32), default=None, nullable=False, comment="数据库类型")

# 动态提供Chunk向量类
# chunk向量类是以群组为最小划分单位
def getChunkModel(group_id):    
    class Chunk(ExtendedBase):
        __tablename__ = "chunk_" + group_id
        id = Column(BIGINT(unsigned = True), primary_key=True, autoincrement=True, comment="chunk库ID")
        file_id = Column(BIGINT(unsigned = True), ForeignKey("file.id") ,nullable=False, comment="文件ID")
        hub_id = Column(BIGINT(unsigned = True), ForeignKey("hub.id"), nullable=False, comment="知识库ID")
        # utf-8每字符最多4字节编码，VARCHAR是指存储的字符数，这里设置最大4K，即文本的chunk长度不能超过4K
        text = Column(VARCHAR(4000), nullable=False, comment="chunk文本内容")
        page = Column(INTEGER(unsigned=True), nullable=False, comment="chunk文本页码")
    
    return Chunk